package neves.android.etmg;

/*
 * 
 *  Game Core Class
 *  main game thread
 * 
 */


import neves.android.etmg.input.InputManager;
import neves.android.etmg.map.GameMap;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.KeyEvent;
import android.view.SurfaceHolder;
import android.view.View;

public class GameCore extends Thread {
	/** Indicate whether the surface has been created & is ready to draw */
	protected boolean isRunning = false;

	/** Handle to the surface manager object we interact with */
	protected SurfaceHolder mainSurfaceHolder;

	/** Message handler used by thread to interact with TextView */
	protected Handler messageHandler;
	
	/** Handle to the application context, used to e.g. fetch Drawables. */
	protected Context mainContext;
	
	/**  */
	protected int gameRound = 0;
	
	//private MapRender mapRender;
	
	protected GameMap currentMap;
	
	protected InputManager inputAgent;
	
	/**
	 * Current height of the surface/canvas.
	 * 
	 * @see #setSurfaceSize
	 */
	protected int mainCanvasHeight = 1;

	/**
	 * Current width of the surface/canvas.
	 * 
	 * @see #setSurfaceSize
	 */
	protected int mainCanvasWidth = 1;

	/** The state of the game. One of READY, RUNNING, PAUSE */
	protected int currentMode;
	/*
	 * State-tracking constants
	 */
	public static final int STATE_PAUSE = 1;
	public static final int STATE_READY = 2;
	public static final int STATE_RUNNING = 3;
	
	public GameCore(SurfaceHolder surfaceHolder, Context context,
			Handler handler) {
		// get handles to some important objects
		mainSurfaceHolder = surfaceHolder;
		messageHandler = handler;
		mainContext = context;

		Resources res = context.getResources();


	}
	
	
	@Override
	public void run() {

		while (isRunning) {
			Canvas c = null;
			try {
				c = mainSurfaceHolder.lockCanvas(null);
				synchronized (mainSurfaceHolder) {
					if (currentMode == STATE_RUNNING){
					
						//updatePhysics();
						if(currentMap.GetMapRender()!=null) currentMap.GetMapRender().DoDraw(c);
					}
					
					//mapRender.DoDraw(c);

				}
			} finally {
				// do this in a finally so that if an exception is thrown
				// during the above, we don't leave the Surface in an
				// inconsistent state
				if (c != null) {
					mainSurfaceHolder.unlockCanvasAndPost(c);
				}
			}
		}
	}
	/**
	 * Sets the game mode. That is, whether we are running, paused, in the
	 * failure state, in the victory state, etc.
	 * 
	 * @see #setState(int, CharSequence)
	 * @param mode
	 *            one of the STATE_* constants
	 */
	public void setState(int mode) {
		synchronized(mainSurfaceHolder) {
			setState(mode, null);
		}
	}

	/**
	 * Sets the game mode. That is, whether we are running, paused, in the
	 * failure state, in the victory state, etc.
	 * 
	 * @param mode
	 *            one of the STATE_* constants
	 * @param message
	 *            string to add to screen or null
	 */
	public void setState(int mode, CharSequence message) {
		/*
		 * This method optionally can cause a text message to be displayed
		 * to the user when the mode changes. Since the View that actually
		 * renders that text is part of the main View hierarchy and not
		 * owned by this thread, we can't touch the state of that View.
		 * Instead we use a Message + Handler to relay commands to the main
		 * thread, which updates the user-text View.
		 */
		synchronized (mainSurfaceHolder) {
			currentMode = mode;
			Log.w("ETMG","Mode"+currentMode);
			if (currentMode == STATE_RUNNING) {
				Message msg = messageHandler.obtainMessage();
				Bundle b = new Bundle();
				b.putString("text", "");
				b.putInt("viz", View.INVISIBLE);
				msg.setData(b);
				messageHandler.sendMessage(msg);
			} else {

				Resources res = mainContext.getResources();
				CharSequence str = "";
				if (currentMode == STATE_READY)
					str = res.getText(R.string.mode_ready);
				else if (currentMode == STATE_PAUSE)
					str = res.getText(R.string.mode_pause);


				if (message != null) {
					str = message + "\n" + str;
				}

				Message msg = messageHandler.obtainMessage();
				Bundle b = new Bundle();
				b.putString("text", str.toString());
				b.putInt("viz", View.VISIBLE);
				msg.setData(b);
				messageHandler.sendMessage(msg);
				// Log.w("ETMG","??");
			}
		}
	}
	
    public Bundle saveState(Bundle map) {
        synchronized (mainSurfaceHolder) {
            if (map != null) {
            }
        }
        return map;
    }
    
	/**
	 * Handles a key-down event.
	 * 
	 * @param keyCode
	 *            the key that was pressed
	 * @param msg
	 *            the original event object
	 * @return true
	 */
	protected boolean doKeyDown(int keyCode, KeyEvent msg) {
		synchronized (mainSurfaceHolder) {
			
			if(inputAgent!=null){
				inputAgent.onKeyDown(keyCode, msg);
			}
				
			return false;
	}
	}
    /**
     * Handles a key-up event.
     * 
     * @param keyCode the key that was pressed
     * @param msg the original event object
     * @return true if the key was handled and consumed, or else false
     */
    boolean doKeyUp(int keyCode, KeyEvent msg) {
        boolean handled = true;
        return handled;
    }
	
    /**
	 * Starts the game, setting parameters for the current difficulty.
	 */
	public void doStart() {
		synchronized (mainSurfaceHolder) {
			setState(STATE_RUNNING);
		}
	}
	
	
	
	/* Callback invoked when the surface dimensions change. */
	public void surfaceChanged(SurfaceHolder holder, int format, int width,
			int height) {
		setSurfaceSize(width, height);
	}

	/* Callback invoked when the surface dimensions change. */
	public void setSurfaceSize(int width, int height) {
		// synchronized to make sure these all change atomically
		synchronized (mainSurfaceHolder) {
			mainCanvasWidth = width;
			mainCanvasHeight = height;

			Log.w("ETMG", String.valueOf(mainCanvasWidth) + "x"
					+ String.valueOf(mainCanvasHeight));

		}
	}
	
	public void SetMap(GameMap newMap){
		synchronized (mainSurfaceHolder) {
			currentMap = newMap;

		}
	}
	public GameMap GetMap(){
		synchronized (mainSurfaceHolder) {
			return currentMap;

		}
	}
    public synchronized void restoreState(Bundle savedState) {
        synchronized (mainSurfaceHolder) {
            setState(STATE_PAUSE);
        }
    }

	/**
	 * Used to signal the thread whether it should be running or not.
	 * Passing true allows the thread to run; passing false will shut it
	 * down if it's already running. Calling start() after this was most
	 * recently called with false will result in an immediate shutdown.
	 * 
	 * @param b
	 *            true to run, false to shut down
	 */
	public void setRunning(boolean b) {
		isRunning = b;
	}

	/**
	 * Resumes from a pause.
	 */
	public void unpause() {

		setState(STATE_RUNNING);
	}

	/**
	 * Pauses the physics update & animation.
	 */
	public void pause() {
		synchronized (mainSurfaceHolder) {
			if (currentMode == STATE_RUNNING)
				setState(STATE_PAUSE);
		}
	}
	
	public void SetInputManager(InputManager newIMer){
		inputAgent = newIMer;
	}
	
	public InputManager GetInputManager(){
		return inputAgent;
	}
	
}
